package com.naiterui.ehp.bs.recommend.controller.medication;


import com.naiterui.common.repository.page.PageParamVO;
import com.naiterui.common.repository.page.PageVO;
import com.naiterui.ehp.bp.bo.esign.RecomSignParamBO;
import com.naiterui.ehp.bp.constants.CommonConstant.ConsultType;
import com.naiterui.ehp.bp.constants.SwaggerTag;
import com.naiterui.ehp.bp.constants.SwaggerTags;
import com.naiterui.ehp.bp.support.exception.BusinessException;
import com.naiterui.ehp.bp.support.exception.PublicService;
import com.naiterui.ehp.bp.support.exception.ResponseVO;
import com.naiterui.ehp.bp.support.security.HeaderConstant;
import com.naiterui.ehp.bs.recommend.exception.ExceptionCodes;
import com.naiterui.ehp.bs.recommend.remote.IEsignFeignClient;
import com.naiterui.ehp.bs.recommend.service.IESignService;
import com.naiterui.ehp.bs.recommend.service.IPrescriptionService;
import com.naiterui.ehp.bs.recommend.service.IRecomCreaterService;
import com.naiterui.ehp.bs.recommend.service.IRecomDraftService;
import com.naiterui.ehp.bs.recommend.service.IRecomService;
import com.naiterui.ehp.bs.recommend.swagger.Tags;
import com.naiterui.ehp.bs.recommend.vo.MedicationPrescriptionVO;
import com.naiterui.ehp.bs.recommend.vo.RecomDetailVO;
import com.naiterui.ehp.bs.recommend.vo.RecomLiteVO;
import com.naiterui.ehp.bs.recommend.vo.RecomRecordVO;
import com.naiterui.ehp.bs.recommend.vo.RecomResultVO;
import com.naiterui.ehp.bs.recommend.vo.RecomVO;
import com.naiterui.ehp.bs.recommend.vo.draft.DraftBoxParamVO;
import com.naiterui.ehp.bs.recommend.vo.draft.DraftBoxVO;
import com.naiterui.ehp.bs.recommend.vo.param.RecomParamVO;
import com.naiterui.ehp.bs.recommend.vo.prescription.PrescriptionVO;
import com.naiterui.ehp.bs.recommend.vo.require.DrRequireListVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.validation.constraints.NotNull;

@Api(tags = SwaggerTag.DOCTOR + SwaggerTag.RECOM)
@RequestMapping("recommend/recom")
@Controller
public class MedicationRecomController {
    private static final Logger LOGGER = LoggerFactory.getLogger(MedicationRecomController.class);

    @Autowired
    private IPrescriptionService prescriptionService;
    @Autowired
    private IRecomService recomService;
    @Autowired
    private IRecomCreaterService recomCreaterService;
    @Autowired
    private IRecomDraftService recomDraftService;

    @Autowired
    private IESignService esignService;

    @Autowired
    private IEsignFeignClient esignFeignClient;


    /**
     * 医生端(3.4.0 以后弃用)
     * 创建推荐单
     * RecomController.save()
     *
     * @param vo
     *
     * @return
     *
     * @throws BusinessException
     * @Author guoyongxiang
     * @Date 2017年7月28日
     * @since 2.9.0
     */

    @ApiOperation( value = "保存推荐记录", notes = "创建推荐单", httpMethod = "POST")
    @RequestMapping("save")
    @ResponseBody
    public ResponseVO<RecomVO> save(@RequestHeader(value = HeaderConstant.HEADER_ORIGIN) Integer origin, Long doctorId,
        @RequestBody RecomParamVO vo) throws BusinessException {
        LOGGER.info("[recom]保存处方单start. doctorId:{}, patientId:{}, vo: {}", doctorId, vo.getPatientId(), vo);
        long start = System.currentTimeMillis();
        Integer requestFrom = this.getRequestFrom(origin);
        RecomVO recomVO = recomCreaterService.saveRecom(doctorId, vo, requestFrom);
        LOGGER.info("[recom]保存处方单end. cost:{}", System.currentTimeMillis() - start);
        return PublicService.returnResponseVO(recomVO);
    }

    /**
     * 处方签名
     * RecomController.sign()
     *
     * @param doctorId
     * @param recomId
     *
     * @return
     *
     * @throws BusinessException
     */

    @ApiOperation(tags = {Tags.APP}, value = "处方签名", notes = "处方签名", httpMethod = "POST")
    @ApiImplicitParams({@ApiImplicitParam(name = "doctorId", value = "医生ID", required = true, dataType = "long", paramType = "query"),
        @ApiImplicitParam(name = "recomId", value = "推荐ID", required = true, dataType = "long", paramType = "query"),
        @ApiImplicitParam(name = "uniqueId", value = "预签名id", dataType = "string", paramType = "query"),
        @ApiImplicitParam(name = "pin", value = "签名PIN码(根据厂商要求传输, SCCA必填)", required = true, dataType = "string", paramType = "query"),})
    @RequestMapping("sign")
    @ResponseBody
    public ResponseVO<Void> sign(@RequestHeader(value = HeaderConstant.HEADER_ORIGIN) Integer origin,
        @NotNull Long doctorId, @NotNull Long recomId, String uniqueId, String pin) throws BusinessException {
        LOGGER.info("[recom]处方单医师签名. doctorId:{}, recomId:{}, uniqueId:{}", doctorId, recomId, uniqueId);
        Integer requestFrom = this.getRequestFrom(origin);
        esignService.sign(recomId, doctorId, uniqueId, pin, requestFrom);
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS);
    }

    /**
     * 发送推荐单
     * RecomController.confirm()
     *
     * @param doctorId
     * @param recomId
     * @param force
     *
     * @return
     *
     * @throws BusinessException
     * @Author guoyongxiang
     * @Date 2017年7月28日
     * @since 2.9.0
     */

    @ApiOperation(tags = {Tags.VERSION290, Tags.APP}, value = "确认推荐", notes = "发送推荐单", httpMethod = "POST")
    @ApiImplicitParams({@ApiImplicitParam(name = "doctorId", value = "医生ID", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "recomId", value = "推荐ID", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "recordId", value = "病历ID", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "force", value = "是否强制推荐", required = true, dataType = "boolean", paramType = "query"),
            @ApiImplicitParam(name = "consultType", value = "推送来源，1:图文咨询，2：视频咨询", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "consultId", value = "咨询Id", required = false, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "uniqueId", value = "预签名id", required = true, dataType = "string", paramType = "query"),})
    @RequestMapping("confirm")
    @ResponseBody
    public ResponseVO<RecomResultVO> confirm(Long doctorId, Long recomId, String recordId, Boolean force, Integer consultType,Long consultId, String uniqueId) throws BusinessException {
        LOGGER.info("[recom]发送推荐start. doctorId:{}, recomId:{}, force:{},consultType:{}, consultId:{}, recordId:{}", doctorId, recomId, force, consultType, consultId, recordId);
        long start = System.currentTimeMillis();

        if (null == doctorId || null == recomId) {
            LOGGER.warn("[recom]发送推荐 recom/confirm ERROR ; param error : doctorId={},recomId={},force={}", doctorId, recomId, force);
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        if (force == null) {
            force = false;
        }
        if (consultType == null) {
            consultType = ConsultType.GRAPHIC;
        }
        RecomResultVO vo = recomCreaterService.saveRecomConfirm(doctorId, recomId, force, consultType, consultId, recordId, uniqueId);

        LOGGER.info("[recom]发送推荐end. cost:{}, recomId:{}", System.currentTimeMillis() - start, recomId);
        return PublicService.returnResponseVO(vo);
    }


    /**
     * 创建推荐单--在原来基础上新增安全用药检查
     */
    @ApiOperation( tags = { SwaggerTags.APP_VIDEO_CONSULT }, value = "保存推荐记录", notes = "创建推荐单", httpMethod = "POST")
    @PostMapping("safe/save")
    @ApiImplicitParams({@ApiImplicitParam(name = "doctorId", value = "医生ID", required = true, dataType = "long", paramType = "query")})
    @ResponseBody
    public ResponseVO<RecomVO> safeSave(@RequestHeader(value = HeaderConstant.HEADER_ORIGIN) Integer origin,
        Long doctorId, @RequestBody RecomParamVO vo) throws BusinessException {
        LOGGER.info("[recom]保存处方单start. doctorId:{}, patientId:{}, vo: {} ", doctorId, vo.getPatientId(), vo);
        long start = System.currentTimeMillis();
        if (doctorId == null) {
            LOGGER.info("保存推荐记录，参数错误:doctorId={}, vo={}", doctorId, vo);
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        Integer requestFrom = this.getRequestFrom(origin);
        RecomVO recomVO = recomCreaterService.saveRecom(doctorId, vo, requestFrom);
        LOGGER.info("[recom]保存处方单end. cost:{}", System.currentTimeMillis() - start);
        return PublicService.returnResponseVO(recomVO);
    }

    /**
     * 再次推荐用药(推药详情)
     *
     * @Description 药品信息(包括限购信息)+处方笺初始化信息
     */
    @RequestMapping("repeat")
    @ApiOperation(value = "一键续方", notes = "医生针对已成功推荐的单子进行二次推荐操作", httpMethod = "POST",tags = {SwaggerTags.APP_DOCTOR_INQUIRER})
    @ApiImplicitParams({@ApiImplicitParam(name = "doctorId", value = "医生ID", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "patientId", value = "患者ID", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "recommendId", value = "推荐单ID", required = true, dataType = "long", paramType = "query")})
    @ResponseBody
    public ResponseVO<MedicationPrescriptionVO> repeat(Long doctorId, Long patientId, Long recommendId) throws BusinessException {
        LOGGER.info("[recom]一键续方 doctorId={}, patientId={}, recommendId={}", doctorId, patientId, recommendId );
        if (null == doctorId || null == recommendId || null == patientId) {
            LOGGER.error("[recom]一键续方参数错误: doctorId={}, patientId={}, recommendId={}", doctorId, patientId,
                         recommendId);
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        MedicationPrescriptionVO medicationPrescription = recomService.getRepeatPrescription(doctorId, recommendId);
        // 处方笺初始化信息
        PrescriptionVO prescription = prescriptionService.getPrescription(doctorId, patientId, medicationPrescription.getInquirerId());
        //增加续方来源
        prescription.setOriginRecom(recommendId);
        medicationPrescription.setPrescription(prescription);

        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS, medicationPrescription);
    }

    /**
     * 医生端查看用药记录
     * MedicationRecomController.medicationList()
     *
     * @param doctorId
     * @param key
     * @param pageVO
     *
     * @return
     *
     * @throws BusinessException
     * @Date 2018年3月21日
     * @since 2.16
     * （医生端优化1.1）新增几个字段就诊人姓名，性别，年龄，共几种药，来源，状态，原因
     */
    @RequestMapping("medication/list")
    @ApiOperation(value = "医生端查询用药记录", notes = "医生端查询用药记录", httpMethod = "POST", tags = {SwaggerTags.APP_DOCTOR_INQUIRER})
    @ApiImplicitParams({
            @ApiImplicitParam(name = "doctorId", value = "医生ID", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "key", value = "患者名称，药品名称", required = false, dataType = "String", paramType = "query")
    })
    @ResponseBody
    public ResponseVO<PageVO<RecomLiteVO>> medicationList(Long doctorId, String key, PageParamVO pageVO) throws BusinessException {

        if (null == doctorId) {
            LOGGER.error("[查询推荐记录] recomSearch ERROR ; param error : doctorId={},key={},pageVO={}", doctorId, key, pageVO);
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        LOGGER.info("[recom]医生端查询用药记录: doctorId={},key={},pageVO={}", doctorId, key, pageVO);
        PageVO<RecomLiteVO> recomLiteVO = recomService.getRecomSearchPage(doctorId, key, pageVO, true);
        return PublicService.returnResponseVO(recomLiteVO);
    }

    /**
     * 查看用药详情
     * MedicationRecomController.medicationDetail()
     *
     * @param id
     * @param doctorId
     *
     * @return
     *
     * @throws BusinessException
     * @Date 2018年3月21日
     * @since 2.16
     */

    @RequestMapping("medication/detail")
    @ApiOperation(value = "根据推荐ID查详情", notes = "查看用药详情", httpMethod = "POST",tags = {SwaggerTags.APP_DOCTOR_INQUIRER})
    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "推荐单ID", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "doctorId", value = "医生ID", required = false, dataType = "long", paramType = "query")})
    @ResponseBody
    public ResponseVO<RecomDetailVO> medicationDetail(Long id, Long doctorId) throws BusinessException {

        if (null == id) {
            LOGGER.error("[根据推荐ID查详情] recomDetail ERROR ; param error : recomId={},doctorId={}", id, doctorId);
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        LOGGER.info("[recom]医生端查看用药详情: doctorId={}, 推荐单ID={}", doctorId, id);
        RecomDetailVO detail = recomService.getRecomSearchDetail(id, doctorId, false);

        return PublicService.returnResponseVO(detail);
    }


    @RequestMapping("record/check")
    @ApiOperation(tags = {Tags.VERSION290, Tags.APP}, value = "发送处方前提醒备案医生校验推药权限", notes = "发送处方前提醒备案医生校验推药权限", httpMethod = "POST")
    @ApiImplicitParams({@ApiImplicitParam(name = "doctorId", value = "医生ID", required = true, dataType = "long", paramType = "query")})
    @ResponseBody
    @Deprecated
    public ResponseVO<RecomRecordVO> checkRecord(Long doctorId) throws BusinessException {
        LOGGER.info("[recom]发送处方前校验备案状态: doctorId={}", doctorId);
        if (doctorId == null) {
            LOGGER.info("发送处方前校验备案状态:doctorId={}", doctorId);
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        RecomRecordVO vo = recomService.getDoctorRecord(doctorId);
        return PublicService.returnResponseVO(vo);
    }

    /**
     * 获取草稿箱信息
     */
    @RequestMapping("/draft/info")
    @ApiOperation(tags = {Tags.VERSION290, Tags.APP}, value = "获取草稿箱信息", notes = "获取草稿箱信息", httpMethod = "POST")
    @ApiImplicitParams({@ApiImplicitParam(name = "doctorId", value = "医生ID", dataType = "long", paramType = "query")})
    @ResponseBody
    public ResponseVO<DraftBoxVO> getDraftInfo(Long doctorId, @RequestBody DraftBoxParamVO draftBoxParamVO)
            throws BusinessException {
        LOGGER.info("[recom]获取草稿箱信息 doctorId={}, draftBoxParamVO={}", doctorId, draftBoxParamVO);
        if (doctorId == null || draftBoxParamVO == null) {
            LOGGER.info("获取草稿箱信息参数错误");
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        DraftBoxVO draftBoxVO = recomDraftService.getDraftInfo(doctorId, draftBoxParamVO);
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS, draftBoxVO);
    }

    /**
     * 校验处方发送条件(限制认证或者备案，或安全限制)
     *
     * @param doctorId
     *
     * @return
     *
     * @throws BusinessException
     */
    @GetMapping("verify/send")
    @ResponseBody
    public ResponseVO<Void> verifySend(Long doctorId, Long inquirerId) throws BusinessException {
        LOGGER.info("[recom]校验处方发送条件(限制认证或者备案，或安全限制) doctorId={}, inquirerId={}", doctorId, inquirerId);
        recomCreaterService.verifyRecomLimit(doctorId, inquirerId);
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS);
    }

    /**
     * （医生端优化1.1）失效处方
     * @param doctorId
     * @param status
     * @param pageVO
     * @return
     * @throws BusinessException
     */
    @RequestMapping("medication/invalid/list")
    @ApiOperation(value = "（医生端优化1.1）失效处方", notes = "查询医生失效处方", httpMethod = "POST", tags = {"医生端优化1.1失效处方"})
    @ApiImplicitParams({
            @ApiImplicitParam(name = "doctorId", value = "医生ID", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "status", value = "状态0全部，1超时未审核，2审核不通过，3超时未购买", required = true, dataType = "int", paramType = "query")
    })
    @ResponseBody
    public ResponseVO<PageVO<RecomLiteVO>> medicationInvalidList(Long doctorId, Integer status, PageParamVO pageVO) throws BusinessException {

        if (null == doctorId) {
            LOGGER.error("[医生端查询失效处方] 参数有误: doctorId={},key={},pageVO={}", doctorId, status, pageVO);
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        LOGGER.info("医生端查询失效处方: doctorId={},status={},pageVO={}", doctorId, status, pageVO);
        PageVO<RecomLiteVO> recomLiteVO = recomService.medicationInvalidList(doctorId, status, pageVO);
        return PublicService.returnResponseVO(recomLiteVO);
    }

    private Integer getRequestFrom(Integer origin) {
        Integer requestFrom = RecomSignParamBO.REQUEST_FROM_APP;
        if (HeaderConstant.HEADER_ORIGIN_DOCTOR_PC == origin) {
            requestFrom = RecomSignParamBO.REQUEST_FROM_PC;
        }
        return requestFrom;
    }

    /**
     * 医生端续方记录
     * @param doctorId
     * @param inquirerId
     * @param pageVO
     * @return
     * @throws BusinessException
     */
    @RequestMapping("require/list")
    @ApiOperation(value = "医生端患者续方记录", notes = "医生端患者续方记录", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "doctorId", value = "医生ID", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "inquirerId", value = "就诊人id", required = true, dataType = "long", paramType = "query")
    })
    @ResponseBody
    public ResponseVO<PageVO<DrRequireListVO>> medicationList(Long doctorId, Long inquirerId, PageParamVO pageVO) throws BusinessException {

        if (null == doctorId || inquirerId == null) {
            LOGGER.error("[医生端患者续方记录] 请求参数有误 : doctorId={},inquirerId={},pageVO={}", doctorId, inquirerId, pageVO);
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        LOGGER.info("[医生端患者续方记录]: doctorId={},inquirerId={},pageVO={}", doctorId, inquirerId, pageVO);
        PageVO<DrRequireListVO> recomLiteVO = recomService.getRequireRecomSearchPage(doctorId, inquirerId, pageVO);
        return PublicService.returnResponseVO(recomLiteVO);
    }


    @RequestMapping("require/detail")
    @ApiOperation(value = "医生主动续方信息", notes = "医生主动续方时所需的处方信息", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "doctorId", value = "医生ID", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "patientId", value = "患者ID", required = true, dataType = "long", paramType = "query"),
            @ApiImplicitParam(name = "recommendId", value = "推荐单ID", required = true, dataType = "long", paramType = "query")})
    @ResponseBody
    public ResponseVO<MedicationPrescriptionVO> drRequireInfo(Long doctorId, Long patientId, Long recommendId) throws BusinessException {
        LOGGER.info("[recom]医生主动续方信息 doctorId={}, patientId={}, recommendId={}", doctorId, patientId, recommendId );
        if (null == doctorId || null == recommendId || null == patientId) {
            LOGGER.error("[recom]医生主动续方信息参数错误: doctorId={}, patientId={}, recommendId={}", doctorId, patientId, recommendId);
            throw new BusinessException(ExceptionCodes.PARAM_ERROR);
        }
        MedicationPrescriptionVO medicationPrescription = recomService.getDrRepeatPrescriptionDetail(doctorId, recommendId);
        // 处方笺初始化信息
        PrescriptionVO prescription = prescriptionService.getPrescription(doctorId, patientId, medicationPrescription.getInquirerId());
        //增加续方来源
        prescription.setOriginRecom(recommendId);
        medicationPrescription.setPrescription(prescription);

        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS, medicationPrescription);
    }
}
